#ifndef _SYS_LIST_H_
#define _SYS_LIST_H_

#include "FanObj.h"
#include "SysTypes.h"

#define LIST_VTABLE(self)   ((ListVTable*)((FanObj*)self)->vtable)


extern Type*    List_classType;
extern VTable*  List_classVTable;


/* [sys::List] Attributes */
struct List
{
  FanObj        super;
};


/* [sys::List] Virtual-table */
typedef struct ListVTable
{
  FanObjVTable  super;
} ListVTable;


/* [sys::List] Methods and fields */
void            List_make(List* self, Type* of, Int capacity);
void            List_makeObj(List* self, Int capacity);
Bool            List_equals(Obj self, NullableObj that);
Int             List_hash(Obj self);
Str*            List_toStr(Obj self);
Int             List_size(List* self);
void            List_setSize(List* self, Int val);
Int             List_capacity(List* self);
void            List_setCapacity(List* self, Int val);
Type*           List_of(List* self);
Bool            List_isEmpty(List* self);
Val             List_get(List* self, Int index);
Val             List_getSafe_1(List* self, Int index);
Val             List_getSafe(List* self, Int index, Val def);
List*           List_getRange(List* self, Range* range);
Bool            List_contains(List* self, Val item);
Bool            List_containsAll(List* self, List* list);
Bool            List_containsAny(List* self, List* list);
NullableInt     List_index_1(List* self, Val item);
NullableInt     List_index(List* self, Val item, Int offset);
NullableInt     List_indexSame_1(List* self, Val item);
NullableInt     List_indexSame(List* self, Val item, Int offset);
Val             List_first(List* self);
Val             List_last(List* self);
List*           List_dup(List* self);
List*           List_set(List* self, Int index, Val item);
List*           List_add(List* self, Val item);
List*           List_addAll(List* self, List* list);
List*           List_insert(List* self, Int index, Val item);
List*           List_insertAll(List* self, Int index, List* list);
Val             List_remove(List* self, Val item);
Val             List_removeSame(List* self, Val item);
Val             List_removeAt(List* self, Int index);
List*           List_removeRange(List* self, Range* r);
List*           List_clear(List* self);
List*           List_trim(List* self);
List*           List_fill(List* self, Val val, Int times);
Val             List_peek(List* self);
Val             List_pop(List* self);
List*           List_push(List* self, Val item);
void            List_each(List* self, Func* c);
void            List_eachr(List* self, Func* c);
void            List_eachRange(List* self, Range* r, Func* c);
NullableObj     List_eachWhile(List* self, Func* c);
NullableObj     List_eachrWhile(List* self, Func* c);
Val             List_find(List* self, Func* c);
NullableInt     List_findIndex(List* self, Func* c);
List*           List_findAll(List* self, Func* c);
List*           List_findType(List* self, Type* t);
List*           List_exclude(List* self, Func* c);
Bool            List_any(List* self, Func* c);
Bool            List_all(List* self, Func* c);
List*           List_map(List* self, Func* c);
NullableObj     List_reduce(List* self, NullableObj init, Func* c);
Val             List_min_0(List* self);
Val             List_min(List* self, Func* c);
Val             List_max_0(List* self);
Val             List_max(List* self, Func* c);
List*           List_unique(List* self);
List*           List_union(List* self, List* that);
List*           List_intersection(List* self, List* that);
List*           List_sort_0(List* self);
List*           List_sort(List* self, Func* c);
List*           List_sortr_0(List* self);
List*           List_sortr(List* self, Func* c);
Int             List_binarySearch_1(List* self, Val key);
Int             List_binarySearch(List* self, Val key, Func* c);
List*           List_reverse(List* self);
List*           List_swap(List* self, Int indexA, Int indexB);
List*           List_moveTo(List* self, Val item, Int toIndex);
List*           List_flatten(List* self);
Val             List_random(List* self);
List*           List_shuffle(List* self);
Str*            List_join_0(List* self);
Str*            List_join_1(List* self, Str* separator);
Str*            List_join(List* self, Str* separator, Func* c);
Str*            List_toCode(List* self);
Bool            List_isRO(List* self);
Bool            List_isRW(List* self);
List*           List_ro(List* self);
List*           List_rw(List* self);


/* [sys::List] Extra methods */
List*           List_new(Type* of, Int capacity);


/* [sys::List] Type-system functions */
Type*           List_initType(void);
VTable*         List_initVTable(void);
void            List_initStatic(void);


#endif
